package com.kun.core;

import java.lang.reflect.Method;
import java.sql.*;

/**
 * 专门负责执行SQL语句的会话对象
 */
public class SqlSession {

    private SqlSessionFactory factory;

    public SqlSession(SqlSessionFactory factory){
        this.factory = factory;
    }

    /**
     * 执行insert语句，向数据库表当中插入记录。
     * @param sqlId sql语句的id
     * @param pojo 插入的数据。
     * @return
     */
    public int insert(String sqlId, Object pojo){
        int count = 0;
        try {
            //获取链接
            Connection connection = factory.getTransaction().getConnection();
            //获取sql
            String originSql = factory.getMappedStatements().get(sqlId).getSql();
            //属性替换成？
            String sql = originSql.replaceAll("#\\{[a-zA-Z0-9_$]*}", "?");
            PreparedStatement ps = connection.prepareStatement(sql);
            // 给?占位符传值
            // 难点：
            // 第一：不知道有多少个?
            // 第二：不知道该将pojo对象中的哪个属性赋值给哪个 ?
            // ps.setString(第几个问号, 传什么值);
            // 缺陷：这里都是setString，所以数据库表中的字段类型要求都是varchar才行

            int fromIndex = 0;
            int index = 1;
            while (true) {
                int jingIndex = originSql.indexOf("#",fromIndex);
                if (jingIndex < 0){
                    break;
                }
                int youkuohaoIndex = originSql.indexOf("}",fromIndex);
                fromIndex = youkuohaoIndex + 1;
                //属性名
                String propertyName = originSql.substring(jingIndex + 2, youkuohaoIndex).trim();
                //get方法
                String methodName = "get" + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);
                Method method = pojo.getClass().getDeclaredMethod(methodName);
                Object propertyValue = method.invoke(pojo);
                //传入参数
                ps.setString(index, propertyValue.toString());
                index++;
            }
            // 执行SQL语句
            count = ps.executeUpdate();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }

        return count;
    }

    /**
     * 执行查询语句，返回一个对象。该方法只适合返回一条记录的sql语句。
     * @param sqlId
     * @param param
     * @return
     */
    public Object selectOne(String sqlId, Object param){
        Object obj = null;
        try {
            //获取连接
            Connection connection = factory.getTransaction().getConnection();

            MappedStatement mappedStatement = factory.getMappedStatements().get(sqlId);
            //返回类型
            String resultType = mappedStatement.getResultType();
            //获取sql
            String originSql = mappedStatement.getSql();
            String sql = originSql.replaceAll("#\\{[a-zA-Z0-9_$]*}", "?");
            //预编译
            PreparedStatement ps = connection.prepareStatement(sql);
            //传值
            ps.setString(1,param.toString());
            //查询结果集
            ResultSet rs = ps.executeQuery();
            //封装结果对象
            if (rs.next()){
                Class<?> resultTypeClass = Class.forName(resultType);
                obj = resultTypeClass.newInstance();
                //给obj对象的哪个属性赋哪个值
                //将查询结果的列名作为属性名,列名是啥，那么属性名就是啥
                ResultSetMetaData rsMetaData = rs.getMetaData();
                int columnCount = rsMetaData.getColumnCount();
                for (int i = 0; i < columnCount; i++) {
                    String propertyName = rsMetaData.getColumnName(i+1);
                    // 拼接方法名
                    String setMethodName = "set" + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);
                    Method setMethod = resultTypeClass.getDeclaredMethod(setMethodName,String.class);
                    // 调用set方法给对象obj属性赋值
                    setMethod.invoke(obj,rs.getString(propertyName));
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }


        return obj;
    }

    /**
     * 提交事务
     */
    public void commit(){
        factory.getTransaction().commit();
    }

    /**
     * 回滚事务
     */
    public void rollback(){
        factory.getTransaction().rollback();
    }

    /**
     * 关闭事务
     */
    public void close(){
        factory.getTransaction().close();
    }
}



















